package paa.simulator;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.Set;

import paa.crawlers.delicious.Crawler;
import paa.simulator.grafo.PessoaVertex;
import paa.simulator.grafo.simple.UndirectedSimpleGraph;
import paa.simulator.heuristic.Heuristic;
import paa.simulator.heuristic.HeuristicFactory;
import paa.simulator.heuristic.HeuristicFactory.HeuristicType;
import paa.simulator.model.Model;
import paa.simulator.model.ModelFactory;
import paa.simulator.model.ModelFactory.ModelType;

public class Main {
	
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {
		if (args == null || args.length < 5) {
			System.err.println("usage: java " + Crawler.class + " <graph object> <model> <payoff | threshold | epsilon (depends on model)> <heuristic> <fraction vertex> <seed (optional)>");
			System.exit(1);
		}
		
		//Loading
		System.out.println("Loading Graph Object");
		ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(args[0])));
		UndirectedSimpleGraph<PessoaVertex> graph = (UndirectedSimpleGraph<PessoaVertex>) ois.readObject();
		ois.close();
		
		System.out.println("Starting simulation with : " + graph.vertexSet().size() + " vertexes");
		//Creating model
		ModelFactory mf = new ModelFactory();
		ModelType modelType = ModelFactory.ModelType.valueOf(args[1]);
		Model model = mf.buildModel(modelType, Double.parseDouble(args[2]));
		
		//Heuristic
		HeuristicType ht = HeuristicType.valueOf(args[3]);
		HeuristicFactory hf = new HeuristicFactory();
		Heuristic heuristic = hf.buildHeuristic(ht);
		
		Double fraction = Double.parseDouble(args[4]);
		int nVertex = (int) (fraction * graph.vertexSet().size());
		Simulator simulator = new Simulator(graph, heuristic, model, nVertex);
		
		if (args.length > 5) {
			String seedString = args[5];
			RandomNumberGenerator.buildInstance(Integer.parseInt(seedString));
		} else {
			RandomNumberGenerator.buildInstance();
		}
		
		int rounds = simulator.run();
		
		Set<PessoaVertex> pvs = graph.vertexSet();
		double qtdBuying = 0;
		for (PessoaVertex pv : pvs) {
			if (pv.isBuying()) qtdBuying++;
		}
		
		System.out.println("Simulation Finished");
		System.out.println("Initial amount buying: " + nVertex);
		System.out.println("Final amount buying: " + qtdBuying);
		System.out.println("Total: " + pvs.size());
		System.out.println("Contagion Fraction: " + qtdBuying / pvs.size());
		System.out.println("Rounds to converge: " + rounds);
	}
}
